package main

import (
	"context"
	"fmt"
	"log"
	"log/slog"
	"os"
	"time"

	"gitee.com/doove/ansible-go"
)

func main() {
	fmt.Println("=== Ansible-Go 高级使用示例 ===")
	
	// 设置结构化日志
	setupLogging()
	
	// 示例 1: 复杂的 Inventory 管理
	complexInventoryExample()
	
	// 示例 2: 高级配置管理
	advancedConfigExample()
	
	// 示例 3: 批量主机操作
	batchOperationsExample()
	
	// 示例 4: 条件执行和错误恢复
	conditionalExecutionExample()
	
	// 示例 5: 自定义模块执行
	customModuleExample()
	
	// 示例 6: 性能监控和日志
	performanceMonitoringExample()
}

func setupLogging() {
	// 创建结构化日志记录器
	logger := ansible.NewJSONLogger(slog.LevelInfo)
	ansible.SetDefaultLogger(logger)
	
	fmt.Println("结构化日志记录器已设置")
}

func complexInventoryExample() {
	fmt.Println("\n--- 示例 1: 复杂的 Inventory 管理 ---")
	
	// 创建复杂的 inventory 结构
	builder := ansible.NewInventoryBuilder()
	
	// Web 服务器组
	webHosts := []*ansible.Host{
		ansible.NewHost("web1", "192.168.1.10").WithUser("deploy").WithPort(22),
		ansible.NewHost("web2", "192.168.1.11").WithUser("deploy").WithPort(22),
		ansible.NewHost("web3", "192.168.1.12").WithUser("deploy").WithPort(22),
	}
	
	for _, host := range webHosts {
		builder.AddHostToGroup("webservers", host)
	}
	
	// 数据库服务器组
	dbHosts := []*ansible.Host{
		ansible.NewHost("db1", "192.168.1.20").WithUser("postgres").WithPort(5432).
			WithVar("db_role", "master"),
		ansible.NewHost("db2", "192.168.1.21").WithUser("postgres").WithPort(5432).
			WithVar("db_role", "slave"),
	}
	
	for _, host := range dbHosts {
		builder.AddHostToGroup("databases", host)
	}
	
	// 负载均衡器
	lbHost := ansible.NewHost("lb1", "192.168.1.30").WithUser("nginx").WithPort(22)
	builder.AddHostToGroup("loadbalancers", lbHost)
	
	// 创建父组
	builder.AddChildGroup("production", "webservers").
		AddChildGroup("production", "databases").
		AddChildGroup("production", "loadbalancers")
	
	// 设置组变量
	builder.SetGroupVars("webservers", map[string]string{
		"http_port":     "80",
		"https_port":    "443",
		"app_env":       "production",
		"log_level":     "info",
	})
	
	builder.SetGroupVars("databases", map[string]string{
		"db_port":       "5432",
		"max_connections": "100",
		"shared_buffers": "256MB",
	})
	
	builder.SetGroupVars("production", map[string]string{
		"ansible_python_interpreter": "/usr/bin/python3",
		"ansible_ssh_common_args":    "-o StrictHostKeyChecking=no",
	})
	
	// 生成并显示 inventory
	inventory := builder.Build()
	fmt.Printf("生成的复杂 Inventory:\n%s\n", inventory)
	
	// 保存到文件
	tempFile, err := builder.ToTempFile()
	if err != nil {
		fmt.Printf("保存 inventory 失败: %v\n", err)
		return
	}
	
	fmt.Printf("Inventory 已保存到: %s\n", tempFile)
}

func advancedConfigExample() {
	fmt.Println("\n--- 示例 2: 高级配置管理 ---")
	
	// 创建生产环境配置
	prodConfig := ansible.DefaultConfig().
		WithBinPath("/usr/local/bin/ansible").
		WithTimeout(5 * time.Minute).
		WithOutputFormat(ansible.OutputFormatJSON).
		WithForceColor(false).
		WithSuppressWarnings(true).
		SetEnvs(map[string]string{
			"ANSIBLE_HOST_KEY_CHECKING":     "False",
			"ANSIBLE_GATHERING":             "smart",
			"ANSIBLE_CACHE_PLUGIN":          "memory",
			"ANSIBLE_CACHE_PLUGIN_TIMEOUT":  "3600",
		})
	
	// 创建开发环境配置
	devConfig := prodConfig.Clone().
		WithTimeout(30 * time.Second).
		WithOutputFormat(ansible.OutputFormatDefault).
		WithForceColor(true).
		WithSuppressWarnings(false).
		SetEnv("ANSIBLE_VERBOSITY", "2")
	
	fmt.Printf("生产环境配置: %+v\n", prodConfig.GetAnsibleEnvs())
	fmt.Printf("开发环境配置: %+v\n", devConfig.GetAnsibleEnvs())
	
	// 使用不同配置创建 Ansible 实例
	inventory := "localhost,"
	
	prodAnsible := ansible.NewAnsible("", inventory, []string{"localhost"}, context.Background())
	// 这里可以应用 prodConfig，但需要修改 NewAnsible 来接受配置
	
	fmt.Printf("生产环境 Ansible 实例创建完成\n")
	
	_ = prodAnsible // 避免未使用变量警告
}

func batchOperationsExample() {
	fmt.Println("\n--- 示例 3: 批量主机操作 ---")
	
	// 创建多主机 inventory
	inventory := ansible.NewInventoryBuilder()
	
	// 添加多个测试主机（模拟）
	hosts := []string{"host1", "host2", "host3", "host4", "host5"}
	for i, hostname := range hosts {
		host := ansible.NewHost(hostname, fmt.Sprintf("192.168.1.%d", 100+i)).
			WithUser("admin").
			WithPort(22)
		inventory.AddHostToGroup("batch_test", host)
	}
	
	tempFile, err := inventory.ToTempFile()
	if err != nil {
		fmt.Printf("创建 inventory 失败: %v\n", err)
		return
	}
	
	// 批量执行操作
	operations := []struct {
		name   string
		module string
		args   string
	}{
		{"系统信息收集", "setup", ""},
		{"磁盘使用情况", "shell", "df -h"},
		{"内存使用情况", "shell", "free -m"},
		{"运行时间", "shell", "uptime"},
		{"网络连接", "shell", "netstat -tuln"},
	}
	
	ans := ansible.NewAnsible("ansible", tempFile, []string{"all"}, context.Background())
	ans.SetOutJson().CloseWarnings()
	
	for _, op := range operations {
		fmt.Printf("\n执行操作: %s\n", op.name)
		
		var stdout, stderr []byte
		var err error
		
		if op.args == "" {
			stdout, stderr, err = ans.RunWithModule(op.module)
		} else {
			stdout, stderr, err = ans.RunWithModule(op.module, op.args)
		}
		
		if err != nil {
			fmt.Printf("操作失败: %v\n", err)
			if len(stderr) > 0 {
				fmt.Printf("错误输出: %s\n", string(stderr))
			}
		} else {
			fmt.Printf("操作成功，输出长度: %d 字节\n", len(stdout))
		}
	}
}

func conditionalExecutionExample() {
	fmt.Println("\n--- 示例 4: 条件执行和错误恢复 ---")
	
	inventory := "localhost,"
	ans := ansible.NewAnsible("ansible", inventory, []string{"localhost"}, context.Background())
	ans.SetOutJson().CloseWarnings()
	
	// 定义一系列可能失败的操作
	operations := []struct {
		name        string
		operation   func() error
		retryCount  int
		continueOnError bool
	}{
		{
			name: "检查服务状态",
			operation: func() error {
				_, _, err := ans.Shell("systemctl status nginx")
				return err
			},
			retryCount:      2,
			continueOnError: true,
		},
		{
			name: "创建备份目录",
			operation: func() error {
				_, _, err := ans.File("/tmp/backup", ansible.ModuleOptions{
					"state": "directory",
					"mode":  "0755",
				})
				return err
			},
			retryCount:      1,
			continueOnError: false,
		},
		{
			name: "备份配置文件",
			operation: func() error {
				_, _, err := ans.Copy("/etc/nginx/nginx.conf", "/tmp/backup/nginx.conf.bak")
				return err
			},
			retryCount:      3,
			continueOnError: true,
		},
	}
	
	successCount := 0
	
	for _, op := range operations {
		fmt.Printf("\n执行操作: %s\n", op.name)
		
		var lastErr error
		success := false
		
		for attempt := 0; attempt <= op.retryCount; attempt++ {
			if attempt > 0 {
				fmt.Printf("重试第 %d 次...\n", attempt)
				time.Sleep(time.Duration(attempt) * time.Second)
			}
			
			err := op.operation()
			if err == nil {
				fmt.Printf("操作成功\n")
				success = true
				break
			}
			
			lastErr = err
			fmt.Printf("尝试 %d 失败: %v\n", attempt+1, err)
		}
		
		if success {
			successCount++
		} else {
			fmt.Printf("操作最终失败: %v\n", lastErr)
			if !op.continueOnError {
				fmt.Printf("由于关键操作失败，停止执行\n")
				break
			}
		}
	}
	
	fmt.Printf("\n总结: %d/%d 操作成功\n", successCount, len(operations))
}

func customModuleExample() {
	fmt.Println("\n--- 示例 5: 自定义模块执行 ---")
	
	inventory := "localhost,"
	ans := ansible.NewAnsible("ansible", inventory, []string{"localhost"}, context.Background())
	ans.SetOutJson().CloseWarnings()
	
	// 使用通用的 RunWithModule 方法执行自定义模块
	customModules := []struct {
		name   string
		module string
		args   string
	}{
		{
			name:   "获取系统负载",
			module: "shell",
			args:   "cat /proc/loadavg",
		},
		{
			name:   "检查磁盘 I/O",
			module: "shell",
			args:   "iostat -x 1 1 | tail -n +4",
		},
		{
			name:   "网络接口状态",
			module: "shell",
			args:   "ip addr show",
		},
		{
			name:   "进程列表",
			module: "shell",
			args:   "ps aux --sort=-%cpu | head -10",
		},
	}
	
	results := make(map[string]interface{})
	
	for _, mod := range customModules {
		fmt.Printf("\n执行自定义模块: %s\n", mod.name)
		
		// 使用解析结果的方法
		result, err := ans.RunWithModuleParsed(mod.module, mod.args)
		if err != nil {
			fmt.Printf("模块执行失败: %v\n", err)
			results[mod.name] = map[string]interface{}{
				"success": false,
				"error":   err.Error(),
			}
		} else {
			fmt.Printf("模块执行成功: %s\n", result.Summary())
			results[mod.name] = map[string]interface{}{
				"success": true,
				"output":  result.Stdout,
				"changed": result.Changed,
			}
		}
	}
	
	fmt.Printf("\n自定义模块执行结果汇总:\n")
	for name, result := range results {
		fmt.Printf("- %s: %+v\n", name, result)
	}
}

func performanceMonitoringExample() {
	fmt.Println("\n--- 示例 6: 性能监控和日志 ---")
	
	// 创建性能监控的日志记录器
	logFile, err := os.Create("/tmp/ansible-go-performance.log")
	if err != nil {
		fmt.Printf("创建日志文件失败: %v\n", err)
		return
	}
	defer logFile.Close()
	
	opts := &slog.HandlerOptions{
		Level: slog.LevelDebug,
	}
	handler := slog.NewJSONHandler(logFile, opts)
	perfLogger := &ansible.Logger{Logger: slog.New(handler)}
	
	// 设置性能日志记录器
	ansible.SetDefaultLogger(perfLogger)
	
	inventory := "localhost,"
	ans := ansible.NewAnsible("ansible", inventory, []string{"localhost"}, context.Background())
	ans.SetOutJson().CloseWarnings()
	
	// 执行一系列操作并监控性能
	operations := []struct {
		name string
		exec func() (time.Duration, error)
	}{
		{
			name: "快速 ping 测试",
			exec: func() (time.Duration, error) {
				start := time.Now()
				_, _, err := ans.Ping()
				return time.Since(start), err
			},
		},
		{
			name: "系统信息收集",
			exec: func() (time.Duration, error) {
				start := time.Now()
				_, _, err := ans.Setup()
				return time.Since(start), err
			},
		},
		{
			name: "文件系统检查",
			exec: func() (time.Duration, error) {
				start := time.Now()
				_, _, err := ans.Shell("df -h && free -m && uptime")
				return time.Since(start), err
			},
		},
	}
	
	fmt.Printf("开始性能监控测试...\n")
	
	totalDuration := time.Duration(0)
	successCount := 0
	
	for _, op := range operations {
		fmt.Printf("\n执行: %s\n", op.name)
		
		duration, err := op.exec()
		totalDuration += duration
		
		if err != nil {
			fmt.Printf("操作失败 (耗时: %v): %v\n", duration, err)
		} else {
			fmt.Printf("操作成功 (耗时: %v)\n", duration)
			successCount++
		}
		
		// 记录性能指标
		perfLogger.InfoContext(context.Background(), "operation completed",
			slog.String("operation", op.name),
			slog.Duration("duration", duration),
			slog.Bool("success", err == nil),
		)
	}
	
	fmt.Printf("\n性能监控总结:\n")
	fmt.Printf("- 总操作数: %d\n", len(operations))
	fmt.Printf("- 成功操作数: %d\n", successCount)
	fmt.Printf("- 总耗时: %v\n", totalDuration)
	fmt.Printf("- 平均耗时: %v\n", totalDuration/time.Duration(len(operations)))
	fmt.Printf("- 性能日志已保存到: /tmp/ansible-go-performance.log\n")
}
